home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / ft_dft.c < prev    next >
C/C++ Source or Header  |  2009-02-22  |  12KB  |  526 lines

  1. /*
  2.  * Modifications Copyright 1996, 1999, 2000 by Paul Mattes.
  3.  * Copyright Octover 1995 by Dick Altenbern.
  4.  * Based in part on code Copyright 1993, 1994, 1995 by Paul Mattes.
  5.  *  Permission to use, copy, modify, and distribute this software and its
  6.  *  documentation for any purpose and without fee is hereby granted,
  7.  *  provided that the above copyright notice appear in all copies and that
  8.  *  both that copyright notice and this permission notice appear in
  9.  *  supporting documentation.
  10.  */
  11.  
  12. /*
  13.  *    tc_dft.c
  14.  *        File transfer: DFT-style data processing functions
  15.  */
  16.  
  17. #include "globals.h"
  18.  
  19. #if defined(X3270_FT) /*[*/
  20.  
  21. #include "appres.h"
  22. #include "3270ds.h"
  23. #include "ft_dft_ds.h"
  24.  
  25. #include "actionsc.h"
  26. #include "kybdc.h"
  27. #include "ft_dftc.h"
  28. #include "ftc.h"
  29. #include "tablesc.h"
  30. #include "telnetc.h"
  31. #include "trace_dsc.h"
  32. #include "utilc.h"
  33.  
  34. #include <errno.h>
  35.  
  36. /* Macros. */
  37. #define OPEN_DATA    "FT:    "    /* Open request for data */
  38. #define OPEN_MSG    "FT:MSG "    /* Open request for message */
  39. #define END_TRANSFER    "TRANS03"    /* Message for xfer complete */
  40.  
  41. /* Typedefs. */
  42. struct data_buffer {
  43.     char sf_length[2];        /* SF length = 0x0023 */
  44.     char sf_d0;            /* 0xD0 */
  45.     char sf_request_type[2];    /* request type */
  46.     char compress_indic[2];        /* 0xc080 */
  47.     char begin_data;        /* 0x61 */
  48.     char data_length[2];        /* Data Length in 3270 byte order+5 */
  49.     char data[256];            /* The actual data */
  50. };
  51.  
  52. struct open_buffer {            /* Buffer passed in open request */
  53.     char sf_request_type[2];    /* 0x0012 for open request */
  54.     char fixed_parms[6];        /* Doc says 010601010403 */
  55.     char func_required[10];        /* Doc says 0a0a0000000011010100 */
  56.     char data_not_compr[5];        /* Doc says 50055203f0 */
  57.     char hdr_length[2];        /* 0x0309 */
  58.     char name[7];            /* ft: or ft:msg */
  59. };
  60. struct error_response {            /* Buffer to build for an error resp. */
  61.     char sf_length[2];        /* 0009 */
  62.     char sf_d0;            /* 0xd0 */
  63.     char sf_tt;            /* tt = 00,47,45,46 */
  64.     char sf_08;            /* 0x08 */
  65.     char sf_err_hdr[2];        /* 0x6904 */
  66.     char sf_err_code[2];        /* The error code */
  67. };
  68. #define UPLOAD_LENGTH 2048-2
  69. struct upload_buffer_hdr {
  70.     char sf_length[2];        /* SF length */
  71.     char sf_d0;            /* 0xd0 */
  72.     char sf_request_type[2];    /* 0x4605 */
  73.     char sf_recnum_hdr[2];        /* 0x6306 */
  74.     char sf_recnum[4];        /* record number in host byte order */
  75.     char sf_compr_indic[2];        /* 0xc080 */
  76.     char sf_begin_data;        /* 0x61 */
  77.     char sf_data_length[2];        /* Data length */
  78. };
  79. struct upload_buffer {
  80.     struct upload_buffer_hdr header;    /* The header */
  81.     /* The actual data */
  82.     char sf_data[UPLOAD_LENGTH - sizeof(struct upload_buffer_hdr)];
  83. };
  84.  
  85. /* Statics. */
  86. static Boolean message_flag = False;    /* Open Request for msg received */
  87. static int eof;
  88. static unsigned long recnum;
  89. static char *abort_string = CN;
  90.  
  91. static void dft_abort(const char *s, unsigned short code);
  92. static void dft_close_request(void);
  93. static void dft_data_insert(struct data_buffer *data_bufr);
  94. static void dft_get_request(void);
  95. static void dft_insert_request(void);
  96. static void dft_open_request(struct open_buffer *open_buf);
  97. static void dft_set_cur_req(void);
  98. static int filter_len(char *s, register int len);
  99.  
  100. /* Process a Transfer Data structured field from the host. */
  101. void
  102. ft_dft_data(unsigned char *data, int length unused)
  103. {
  104.     struct data_buffer *data_bufr = (struct data_buffer *)data;
  105.     unsigned short data_type;
  106.     unsigned char *cp;
  107.  
  108.     if (ft_state == FT_NONE) {
  109.         trace_ds(" (no transfer in progress)\n");
  110.         return;
  111.     }
  112.  
  113.     /* Position to character after the d0. */
  114.     cp = (unsigned char *)(data_bufr->sf_request_type);
  115.  
  116.     /* Get the function type */
  117.     GET16(data_type, cp);
  118.  
  119.     /* Handle the requests */
  120.     switch (data_type) {
  121.         case TR_OPEN_REQ:
  122.         dft_open_request((struct open_buffer *)cp);
  123.         break;
  124.         case TR_INSERT_REQ:    /* Insert Request */
  125.         dft_insert_request();
  126.         break;
  127.         case TR_DATA_INSERT:
  128.         dft_data_insert(data_bufr);
  129.         break;
  130.         case TR_SET_CUR_REQ:
  131.         dft_set_cur_req();
  132.         break;
  133.         case TR_GET_REQ:
  134.         dft_get_request();
  135.         break;
  136.         case TR_CLOSE_REQ:
  137.         dft_close_request();
  138.         break;
  139.         default:
  140.         trace_ds(" Unsupported(0x%04x)\n", data_type);
  141.         break;
  142.     }
  143. }
  144.  
  145. /* Process an Open request. */
  146. static void
  147. dft_open_request(struct open_buffer *open_buf)
  148. {
  149.     trace_ds(" Open %*.*s\n", 7, 7, open_buf->name);
  150.  
  151.     if (memcmp(open_buf->name, OPEN_MSG, 7) == 0 )
  152.         message_flag = True;
  153.     else {
  154.         message_flag = False;
  155.         ft_running(False);
  156.     }
  157.     eof = False;
  158.     recnum = 1;
  159.  
  160.     trace_ds("> WriteStructuredField FileTransferData OpenAck\n");
  161.     obptr = obuf;
  162.     space3270out(6);
  163.     *obptr++ = AID_SF;
  164.     SET16(obptr, 5);
  165.     *obptr++ = SF_TRANSFER_DATA;
  166.     SET16(obptr, 9);
  167.     net_output();
  168. }
  169.  
  170. /* Process an Insert request. */
  171. static void
  172. dft_insert_request(void)
  173. {
  174.     trace_ds(" Insert\n");
  175.     /* Doesn't currently do anything. */
  176. }
  177.  
  178. /* Process a Data Insert request. */
  179. static void
  180. dft_data_insert(struct data_buffer *data_bufr)
  181. {
  182.     /* Received a data buffer, get the length and process it */
  183.     int my_length;
  184.     unsigned char *cp;
  185.  
  186.     trace_ds(" Data\n");
  187.  
  188.     if (!message_flag && ft_state == FT_ABORT_WAIT) {
  189.         dft_abort(get_message("ftUserCancel"), TR_DATA_INSERT);
  190.         return;
  191.     }
  192.  
  193.     cp = (unsigned char *) (data_bufr->data_length);
  194.  
  195.     /* Get the data length in native format. */
  196.     GET16(my_length, cp);
  197.  
  198.     /* Adjust for 5 extra count */
  199.     my_length -= 5;
  200.  
  201.     /*
  202.      * First, check to see if we have message data or file data.
  203.      * Message data will result in a popup.
  204.      */
  205.     if (message_flag) {
  206.         /* Data is from a message */
  207.         unsigned char *msgp;
  208.         unsigned char *dollarp;
  209.  
  210.         /* Get storage to copy the message. */
  211.         msgp = (unsigned char *)Malloc(my_length + 1);
  212.  
  213.         /* Copy the message. */
  214.         memcpy(msgp, data_bufr->data, my_length);
  215.  
  216.         /* Null terminate the string. */
  217.         dollarp = (unsigned char *)memchr(msgp, '$', my_length);
  218.         if (dollarp != NULL)
  219.             *dollarp = '\0';
  220.         else
  221.             *(msgp + my_length) = '\0';
  222.  
  223.         /* If transfer completed ok, use our msg. */
  224.         if (memcmp(msgp, END_TRANSFER, strlen(END_TRANSFER)) == 0) {
  225.             Free(msgp);
  226.             ft_complete((String)NULL);
  227.         } else if (ft_state == FT_ABORT_SENT && abort_string != CN) {
  228.             Free(msgp);
  229.             ft_complete(abort_string);
  230.             Free(abort_string);
  231.             abort_string = CN;
  232.         } else {
  233.             ft_complete((char *)msgp);
  234.             Free(msgp);
  235.         }
  236.     } else if (my_length > 0) {
  237.         /* Write the data out to the file. */
  238.         int rv = 1;
  239.  
  240.         if (ascii_flag && remap_flag) {
  241.             /* Filter. */
  242.             unsigned char *s = (unsigned char *)data_bufr->data;
  243.             unsigned len = my_length;
  244.  
  245.             while (len--) {
  246.                 *s = ft2asc[*s];
  247.                 s++;
  248.             }
  249.         }
  250.         if (ascii_flag && cr_flag) {
  251.             char *s = (char *)data_bufr->data;
  252.             unsigned len = my_length;
  253.  
  254.             /* Delete CRs and ^Zs. */
  255.             while (len) {
  256.                 unsigned l = filter_len(s, len);
  257.  
  258.                 if (l) {
  259.                     rv = fwrite(s, l, (size_t)1,
  260.                         ft_local_file);
  261.                     if (rv == 0)
  262.                         break;
  263.                     ft_length += l;
  264.                 }
  265.                 if (l < len)
  266.                     l++;
  267.                 s += l;
  268.                 len -= l;
  269.             }
  270.         } else {
  271.             rv = fwrite((char *)data_bufr->data, my_length,
  272.                 (size_t)1, ft_local_file);
  273.             ft_length += my_length;
  274.         }
  275.  
  276.         if (!rv) {
  277.             /* write failed */
  278.             char *buf;
  279.  
  280.             buf = xs_buffer("write(%s): %s", ft_local_filename,
  281.                 strerror(errno));
  282.  
  283.             dft_abort(buf, TR_DATA_INSERT);
  284.             Free(buf);
  285.         }
  286.  
  287.         /* Add up amount transferred. */
  288.         ft_update_length();
  289.     }
  290.  
  291.     /* Send an acknowledgement frame back. */
  292.     trace_ds("> WriteStructuredField FileTransferData DataAck(%lu)\n",
  293.         recnum);
  294.     obptr = obuf;
  295.     space3270out(12);
  296.     *obptr++ = AID_SF;
  297.     SET16(obptr, 11);
  298.     *obptr++ = SF_TRANSFER_DATA;
  299.     SET16(obptr, TR_NORMAL_REPLY);
  300.     SET16(obptr, TR_RECNUM_HDR);
  301.     SET32(obptr, recnum);
  302.     recnum++;
  303.     net_output();
  304. }
  305.  
  306. /* Process a Set Cursor request. */
  307. static void
  308. dft_set_cur_req(void)
  309. {
  310.     trace_ds(" SetCursor\n");
  311.     /* Currently doesn't do anything. */
  312. }
  313.  
  314. /* Process a Get request. */
  315. static void
  316. dft_get_request(void)
  317. {
  318.     int numbytes;
  319.     size_t numread;
  320.     unsigned char *bufptr;
  321.     struct upload_buffer *upbufp;
  322.  
  323.     trace_ds(" Get\n");
  324.  
  325.     if (!message_flag && ft_state == FT_ABORT_WAIT) {
  326.         dft_abort(get_message("ftUserCancel"), TR_GET_REQ);
  327.         return;
  328.     }
  329.  
  330.     /*
  331.      * This is a request to send an upload buffer.
  332.      * First check to see if we are finished (eof = True).
  333.      */
  334.     if (eof) {
  335.         /* We are done, send back the eof error. */
  336.         trace_ds("> WriteStructuredField FileTransferData EOF\n");
  337.         space3270out(sizeof(struct error_response) + 1);
  338.         obptr = obuf;
  339.         *obptr++ = AID_SF;
  340.         SET16(obptr, sizeof(struct error_response));
  341.         *obptr++ = SF_TRANSFER_DATA;
  342.         *obptr++ = HIGH8(TR_GET_REQ);
  343.         *obptr++ = TR_ERROR_REPLY;
  344.         SET16(obptr, TR_ERROR_HDR);
  345.         SET16(obptr, TR_ERR_EOF);
  346.     } else {
  347.         trace_ds("> WriteStructuredField FileTransferData Data(%lu)\n",
  348.             recnum);
  349.         space3270out(sizeof(struct upload_buffer) + 1);
  350.         obptr = obuf;
  351.         *obptr++ = AID_SF;
  352.         /* Set buffer pointer */
  353.         upbufp = (struct upload_buffer *) obptr;
  354.         /* Skip length for now */
  355.         obptr += 2;
  356.         *obptr++ = SF_TRANSFER_DATA;
  357.         SET16(obptr, TR_GET_REPLY);
  358.         SET16(obptr, TR_RECNUM_HDR);
  359.         SET32(obptr, recnum);
  360.         recnum++;
  361.         SET16(obptr, TR_NOT_COMPRESSED);
  362.         *obptr++ = TR_BEGIN_DATA;
  363.  
  364.         /* Size of the data buffer */
  365.         numbytes = sizeof(upbufp->sf_data);
  366.         SET16(obptr, numbytes+5);
  367.         bufptr = (unsigned char *)upbufp->sf_data;
  368.         obptr = (unsigned char *)upbufp->header.sf_data_length;
  369.         while (numbytes > 1) {
  370.             /* Continue until we run out of buffer */
  371.             if (cr_flag) {
  372.                 /* Insert CR after LF. */
  373.                 if (fgets((char *)bufptr, numbytes,
  374.                         ft_local_file) != CN) {
  375.                     /* We got a line. */
  376.  
  377.                     /* Filter. */
  378.                     {
  379.                         unsigned char *s = bufptr;
  380.  
  381.                         while (*s) {
  382.                             *s = asc2ft[*s];
  383.                             s++;
  384.                         }
  385.                     }
  386.  
  387.                     /* Decrement left. */
  388.                     numbytes -= (strlen((char *)bufptr)+1);
  389.  
  390.                     /* Point to \r at end of str. */
  391.                     bufptr += (strlen((char *)bufptr)-1);
  392.  
  393.                     if (*bufptr == '\n') {
  394.                         /* Stick in the \r\n. */
  395.                         memcpy(bufptr, "\r\n", 2);
  396.                     }
  397.  
  398.                     /* Point to next space. */
  399.                     bufptr += 2;
  400.  
  401.                     if (numbytes == 0) {
  402.                         /* At end of buffer */
  403.                         if (*(bufptr - 1) != '\n') {
  404.                             /*
  405.                              * If not a LF, Back up
  406.                              * the buff pointer.
  407.                              */
  408.                             bufptr--;
  409.                         }
  410.                     }
  411.                 }
  412.             } else {
  413.                     /* Not crlf, do binary read. */
  414.                 numread = fread(bufptr, 1, numbytes,
  415.                     ft_local_file);
  416.                 if (ascii_flag && remap_flag) {
  417.                     unsigned char *s = bufptr;
  418.                     int i = numread;
  419.  
  420.                     while (i) {
  421.                         *s = asc2ft[*s];
  422.                         s++;
  423.                         i--;
  424.                     }
  425.                 }
  426.                 bufptr += numread;
  427.                 numbytes -= numread;
  428.             }
  429.             if (feof(ft_local_file)) {
  430.                 /* End of file. */
  431.  
  432.                 /* Set that we are out of data. */
  433.                 eof = True;
  434.                 break;
  435.             } else if (ferror(ft_local_file)) {
  436.                 char *buf;
  437.  
  438.                 buf = xs_buffer("read(%s): %s",
  439.                     ft_local_filename,
  440.                     strerror(errno));
  441.                 dft_abort(buf, TR_GET_REQ);
  442.             }
  443.         }
  444.  
  445.         /* Set data length. */
  446.         SET16(obptr, bufptr-obptr+4);
  447.  
  448.         /* Accumulate length written. */
  449.         ft_length += bufptr-obptr;
  450.  
  451.         /* Send last byte to net_output. */
  452.         obptr = bufptr;
  453.     }
  454.  
  455.     /* We built a buffer, let's write it back to the mainframe. */
  456.  
  457.     /* Position to beg. of buffer. */
  458.     bufptr = obuf;
  459.     bufptr++;
  460.  
  461.     /* Set the sf length. */
  462.     SET16(bufptr, (obptr-1)-obuf);
  463.  
  464.     net_output();
  465.     ft_update_length();
  466. }
  467.  
  468. /* Process a Close request. */
  469. static void
  470. dft_close_request(void)
  471. {
  472.     /*
  473.      * Recieved a close request from the system.
  474.      * Return a close acknowledgement.
  475.      */
  476.     trace_ds(" Close\n");
  477.     trace_ds("> WriteStructuredField FileTransferData CloseAck\n");
  478.     obptr = obuf;
  479.     space3270out(6);
  480.     *obptr++ = AID_SF;
  481.     SET16(obptr, 5);    /* length */
  482.     *obptr++ = SF_TRANSFER_DATA;
  483.     SET16(obptr, TR_CLOSE_REPLY);
  484.     net_output();
  485. }
  486.  
  487. /* Abort a transfer. */
  488. static void
  489. dft_abort(const char *s, unsigned short code)
  490. {
  491.     if (abort_string != CN)
  492.         Free(abort_string);
  493.     abort_string = NewString(s);
  494.  
  495.     trace_ds("> WriteStructuredField FileTransferData Error\n");
  496.  
  497.     obptr = obuf;
  498.     space3270out(10);
  499.     *obptr++ = AID_SF;
  500.     SET16(obptr, 9);    /* length */
  501.     *obptr++ = SF_TRANSFER_DATA;
  502.     *obptr++ = HIGH8(code);
  503.     *obptr++ = TR_ERROR_REPLY;
  504.     SET16(obptr, TR_ERROR_HDR);
  505.     SET16(obptr, TR_ERR_CMDFAIL);
  506.     net_output();
  507.  
  508.     /* Update the pop-up and state. */
  509.     ft_aborting();
  510. }
  511.  
  512. /* Returns the number of bytes in s, limited by len, that aren't CRs or ^Zs. */
  513. static int
  514. filter_len(char *s, register int len)
  515. {
  516.     register char *t = s;
  517.  
  518.     while (len && *t != '\r' && *t != 0x1a) {
  519.         len--;
  520.         t++;
  521.     }
  522.     return t - s;
  523. }
  524.  
  525. #endif /*]*/
  526.